import useClipboard from "vue-clipboard3";
import { ElMessage } from "element-plus";
import { cloneDeep } from "lodash-es";

// 百分比格式化
export function percentFormat(row: EmptyArrayType, column: number, cellValue: string) {
	return cellValue ? `${cellValue}%` : "-";
}

// 小数格式化
export function scaleFormat(value: string = "0", scale: number = 4) {
	return Number.parseFloat(value).toFixed(scale);
}

// 小数格式化
export function scale2Format(value: string = "0") {
	return Number.parseFloat(value).toFixed(2);
}

// 金额格式化（分转元，保留两位小数）
export function money2Format(value: number) {
	return (value / 100).toFixed(2);
}

// 点击复制文本
const { toClipboard } = useClipboard();
export function copyText(text: string) {
	return new Promise((resolve, reject) => {
		try {
			// 复制
			toClipboard(text);
			// 下面可以设置复制成功的提示框等操作
			ElMessage.success("复制成功!");
			resolve(text);
		} catch (e) {
			// 复制失败
			ElMessage.error("复制失败!");
			reject(e);
		}
	});
}

// 获取 url 上指定 key 的 query 数据
export function getUrlQuery(url: string, key: string) {
	const index = url.indexOf("?");
	if (index !== -1) {
		const queryStrArr = url.substring(index + 1).split("&");
		for (var i = 0; i < queryStrArr.length; i++) {
			const itemArr = queryStrArr[i].split("=");
			if (itemArr[0] === key) {
				return itemArr[1];
			}
		}
	}
	return null;
}

// 把参数对象转换为query参数字符串
export function concatParams(params: EmptyObjectType) {
	let paramStr = "";
	let count = 0;
	for (const key in params) {
		if (Object.hasOwnProperty.call(params, key)) {
			if (count === 0) {
				paramStr += `${key}=${params[key]}`;
			} else {
				paramStr += `&${key}=${params[key]}`;
			}
			count++;
		}
	}
	return paramStr;
}

/**
 * 传入的参数类型 ->  返回值
 * 0						  ->  "Number"
 * ""						  ->  "String"
 * []             ->  "Array"
 * {}             ->  "Object"
 * function(){}   ->  "Function"
 * null           ->  "Null"
 * undefined      ->  "Undefined"
 * true / false   ->  "Boolean"
 * new Date()     ->  "Date"
 * new Error()    ->  "Error"
 * new RegExp()   ->  "RegExp"
 */
export function whoami(val: any) {
	return Object.prototype.toString.call(val).slice(8, -1);
}

// 格式化错误信息
export function formatErrMsg(err: any) {
	return whoami(err) === "String" ? err : JSON.stringify(err);
}

// 删除对象中的空值
export function deleteEmptyProperty(data: EmptyObjectType) {
	const cloneData = cloneDeep(data);
	Object.keys(data).forEach(key => {
		if (whoami(data[key]) === "String") cloneData[key] = cloneData[key].trim();
		if (data[key] === null || data[key] === undefined || data[key] === "") delete cloneData[key];
	});
	return cloneData;
}

// 根据索引截取子数组
export function getSubArrayByIndex(arr: EmptyArrayType, index: number) {
	return arr.slice(0, index + 1);
}

/**
 * 构造树形结构数据
 * @param {*} data 数据源
 * @param {*} orderNum 排序字段 默认 'order_num'
 * @param {*} parentId 父节点字段 默认 'parent'
 * @param {*} rootId 根Id 默认从 data 中获取最小的 parent 值
 */
export function constructTree(
	data: EmptyArrayType,
	orderNum: string = "order_num",
	parentId: string = "parent",
	rootId?: number
) {
	// 确定根节点的id值
	rootId = rootId || Math.min(...data.map(item => item[parentId]));
	// 对源数据深度克隆
	const cloneData = JSON.parse(JSON.stringify(data));
	// 循环所有项
	const treeData = cloneData.filter((father: any) => {
		// 构造路由树时，如果存在重定向且为 noRedirect，则删除重定向属性
		if (father.redirect && father.redirect === "noRedirect") delete father.redirect;
		// 返回每一项的子级数组
		const branchArr = cloneData.filter((child: any) => {
			return child[parentId] === father.id;
		});
		// 如果存在子级，则给它们排序并连接到父级的 children 属性上
		if (branchArr.length > 0) {
			branchArr.sort((a: EmptyObjectType, b: EmptyObjectType) => a[orderNum] - b[orderNum]);
			father.children = branchArr;
		}
		// 返回树形结构数据的第一层
		return !father[parentId] || father[parentId] === rootId;
	});
	// 循环结束后，排序并返回树形结构数据
	treeData.sort((a: EmptyObjectType, b: EmptyObjectType) => a[orderNum] - b[orderNum]);
	return treeData.length > 0 ? treeData : data;
}

/**
 * 根据数组中的某个字段进行排序
 * @param orgArr 被排序的数组
 * @param sortArr 参照排序的数组
 * @param key 排序的字段
 */
export function orderArrByArr(orgArr: EmptyArrayType, sortArr: EmptyArrayType, key: string) {
	const getIndex = (arr: EmptyArrayType, key: string) => {
		const index = arr.indexOf(key);
		return index != -1 ? index : 10000;
	};
	orgArr.sort((a, b) => {
		return getIndex(sortArr, a[key]) > getIndex(sortArr, b[key]) ? 1 : -1;
	});
}

/**
 * 轮询（利用 setTimeout 实现）
 * @param pollingFunc 需要循环执行的函数
 * @param changeFunc 轮询状态改变时执行的函数
 * @param interval 循环执行的间隔，单位毫秒，默认 5000
 * @returns 对象 { start, end }: start 轮询开始函数（参数 isFirst: 是否立刻执行 pollingFunc）、stop 轮询停止函数
 */
export function myPolling(
	pollingFunc: (stop: Function) => Promise<any>,
	changeFunc: (isRunning: boolean) => void,
	interval: number = 5000
) {
	let timer: any;
	let isStop: boolean;
	// 轮询执行
	async function loop(opIsStop: boolean, opIsFirst: boolean): Promise<any> {
		if (opIsStop) return;
		if (!opIsFirst) return (timer = setTimeout(() => loop(isStop, true), interval));
		try {
			await pollingFunc(stop); // 传入 stop 函数，方便在 pollingFunc 中主动停止轮询
		} catch (error) {
			stop();
			console.error("轮询出错", error);
		}
		return (timer = setTimeout(() => loop(isStop, true), interval));
	}
	// 轮询开始 -> isFirst 是否立刻执行第一次，默认true
	function start(isFirst = true) {
		console.log("轮询开始");
		isStop = false;
		changeFunc(!isStop);
		loop(isStop, isFirst);
	}
	// 轮询停止
	function stop() {
		console.log("轮询停止");
		isStop = true;
		changeFunc(!isStop);
		clearTimeout(timer);
	}
	return { start, stop };
}

/**
 * 桌面通知（Web Notification API）
 * @param body 通知内容
 */
export function myNotification(body: string) {
	return new Notification("非急救转运调度平台", { icon: "/favicon.ico", body });
}

/**
 * 可暂停的定时器类
 * @param callback 回调函数
 * @param delay 延迟时间，单位毫秒
 * @param remaining 剩余时间，单位毫秒
 * @param timerId 定时器ID
 * @param start 定时器开始时间
 * @function startTimer() 启动定时器
 * @function pause() 暂停定时器
 * @function resume() 恢复定时器
 * @function clear() 清除定时器
 */
export class PausableTimeout {
	callback: Function;
	delay: number;
	remaining: number;
	timerId: number | null;
	start: number | null;
	constructor(callback: Function, delay: number) {
		this.callback = callback;
		this.delay = delay;
		this.remaining = delay;
		this.timerId = null;
		this.start = null;
	}

	// 启动定时器
	startTimer() {
		this.start = Date.now(); // 记录定时器的启动时间戳(毫秒)
		this.timerId = setTimeout(() => {
			this.callback();
			this.clear();
		}, this.remaining);
	}

	// 暂停定时器
	pause() {
		clearTimeout(this.timerId as number);
		this.remaining -= Date.now() - this.start!;
		if (this.remaining < 0) this.remaining = 0;
	}

	// 恢复定时器
	resume() {
		this.startTimer();
	}

	// 清除定时器
	clear() {
		clearTimeout(this.timerId as number);
		this.callback = () => {};
		this.delay = 0;
		this.remaining = this.delay;
		this.timerId = null;
		this.start = null;
	}
}
